#include <iostream>
#include <fstream>
#include <string.h>
#include <ClassHeap.h>
#include <ObjectHeap.h>
#include <ExecutionEngine.h>
#include "JavaClass.h"
#include "Config.h"
using namespace std;

void Execute(string filePath){
    string path = filePath + ".class";
    ClassHeap heap;
    JavaClass* pClass1 = NULL,*pClass2 = NULL,*pClass3 =  NULL;
    pClass1 = new JavaClass();
    pClass2 = new JavaClass();

    bool bRet = heap.LoadClass(filePath,pClass1);
    
    if (bRet == false) {
        cout<<"failed in load java class file"<<endl;
        return;
    }
    
    bRet = heap.LoadClass(std::string("java.lang.Object"), pClass2);
    
    ObjectHeap objectHeap;

    Frame* pFrameStack = new Frame[20];
    memset(pFrameStack,0, sizeof(Frame) * 20);

    for(int i = 0;i < 20;i++){
        pFrameStack[i].pBaseFrame = pFrameStack;
    }
    pFrameStack[0].pOpStack = new Variable[100];
    memset(pFrameStack[0].pOpStack,0, sizeof(Variable) *  100);
    for(int i = 1;i < 20;i++){
        pFrameStack[i].pOpStack = pFrameStack[0].pOpStack;
    }

    ExecutionEngine ex;
    ex.pClassHeap = &heap;
    ex.pObjectHeap = &objectHeap;
    int startFrame = 0;

    Object object = objectHeap.CreateObject(pClass1);
    JavaClass* pVirtualClass = pClass1;
    int mainIndex = pClass1->GetMethodIndex(string("main"),string("()I"),pVirtualClass);

    if (mainIndex < 0 || mainIndex >= pClass1->methods_count) {
        cout<<"can not fine main method"<<endl;
        goto freeResource;
    }

    pFrameStack[startFrame].pClass = pVirtualClass;
    pFrameStack[startFrame].pMethod = &pVirtualClass->methods[mainIndex];
    pFrameStack[startFrame].stack = pFrameStack->pOpStack;
    pFrameStack[startFrame].sp = pFrameStack[startFrame].pMethod->pCode_attr->max_locals;
    pFrameStack[startFrame].stack[0].object = object;
    ex.Execute(&pFrameStack[startFrame]);

freeResource:
    delete [] pFrameStack[0].pOpStack;
    delete [] pFrameStack;
    return;
}

int main(int argc, char *argv[]) {
    //cout << "Hello, World!" << endl;
    //std::string filePath(JAVA_DIR);
    //filePath+="/Test";
    std::string filePath;
    if (argc < 2) {
        cout<<"no java class is indicate"<<endl;
        return -1;
    }else{
        filePath += argv[1];
    }
    Execute(filePath);
    return 0;
}
